#include "apb_gpio.h"

/* ================== 驱动实现 ================== */

void gpio_set_dir(uint32_t mask, uint32_t value) {
  mask &= GPIO_MASK;
  value &= GPIO_MASK;
  uint32_t dir = REG32(REG_DIR);
  dir = (dir & ~mask) | (value & mask);
  REG32(REG_DIR) = dir;
}

void gpio_write_all(uint32_t value) { REG32(REG_OUT) = (value & GPIO_MASK); }

void gpio_set_bits(uint32_t mask) { REG32(REG_SET) = (mask & GPIO_MASK); }

void gpio_clr_bits(uint32_t mask) { REG32(REG_CLR) = (mask & GPIO_MASK); }

void gpio_tog_bits(uint32_t mask) { REG32(REG_TOG) = (mask & GPIO_MASK); }

uint32_t gpio_read_in(void) { return REG32(REG_IN) & GPIO_MASK; }

uint32_t gpio_read_out(void) { return REG32(REG_OUT) & GPIO_MASK; }

uint32_t gpio_read_dir(void) { return REG32(REG_DIR) & GPIO_MASK; }

/* ================== 流水灯示例 ================== */

/* 可调的延时循环次数（根据你的 CPU 主频调节） */
#ifndef CHASER_DELAY_CYCLES
#define CHASER_DELAY_CYCLES (100000u)
#endif

static void busy_delay(volatile uint32_t n) {
  while (n--) {
    __asm__ volatile("nop");
  }
}

/* 选择用哪些引脚做 LED（默认用低 8 位；如果 GPIO 宽度小于 8，则全用） */
#ifndef LED_MASK
#if GPIO_WIDTH >= 8
#define LED_MASK (0xFFu)
#else
#define LED_MASK ((1u << GPIO_WIDTH) - 1u)
#endif
#endif

int main(void) {
  /* 1) 把 LED_MASK 覆盖的引脚设为输出，其余保持不变 */
  gpio_set_dir(LED_MASK, LED_MASK);

  /* 2) 先全灭（只写 LED 的那几位，其它位保持 0） */
  gpio_clr_bits(LED_MASK);

  /* 3) 跑马灯：从低位往高位移动，再从高位往低位移动，循环往复 */
  for (;;) {
    /* 向左跑（低 -> 高） */
    for (unsigned i = 0; i < 32; ++i) {
      uint32_t bit = (1u << i);
      if ((bit & LED_MASK) == 0)
        continue; // 跳过不在 LED_MASK 内的位

      gpio_write_all(bit & LED_MASK); // 只点亮一个 LED
      busy_delay(CHASER_DELAY_CYCLES);
    }

    /* 向右跑（高 -> 低） */
    for (int i = 31; i >= 0; --i) {
      uint32_t bit = (1u << i);
      if ((bit & LED_MASK) == 0)
        continue;

      gpio_write_all(bit & LED_MASK);
      busy_delay(CHASER_DELAY_CYCLES);
    }
  }

  /* 不会到这里 */
  // return 0;
}
